import json
import os
import imghdr

import core

def _get_resource_path(base:str, *levels:str, file_type:str=None) -> str:
    if len(levels) < 1:
        raise ValueError("Require a file at least")
    postfix = "" if not file_type else "." + file_type
    return os.path.realpath(os.path.join(base,*levels)) + postfix

def load_deck(file:str, card:dict) -> core.Deck:
    try:
        with open(file,"r",encoding="utf-8") as f:
            text = f.read()
        data = json.loads(text)
        deck = data["deck"]
        deck + []
    except OSError as e:
        raise core.AppError("deck_not_found","Deck located at {} not found".format(file)) from e
    except json.JSONDecodeError as e:
        raise core.AppError("deck_invalid","Deck located at {} invalid".format(file)) from e
    except KeyError as e:
        raise core.AppError("deck_no_deck_key","Deck loacated at {} requires deck key".format(file)) from e
    except TypeError as e:
        raise core.AppError("deck_bad_deck","Deck loacated at {}'s key 'deck' must be an array".format(file)) from e
    try:
        for i in deck:
            i + []
            i[0] + ""
            i[1] + 0
    except TypeError as e:
        raise core.AppError("deck_bad_deck_element","Deck loacated at {}'s key 'deck' has 1 or more bad elements, which should be array like [name:str, count:int]".format(file)) from e
    return core.Deck(deck,card_width=card["width"],card_height=card["height"], name=os.path.basename(file))

@core.cached
def get_card_data(base:str, name:str):
    levels_front  = [name]
    levels_back = ["back", name]

    path_front = _get_resource_path(base, "card", *levels_front, file_type="png")
    path_back = _get_resource_path(base, "card", *levels_back, file_type="png")

    try:
        with open(path_front,"rb") as f: pass
        with open(path_back,"rb") as f: pass
    except OSError as e:
        raise core.AppError("card_no_file:{}".format(name)) from e
    try:
        if imghdr.what(path_front) != "png" or imghdr.what(path_back) != "png":
            raise TypeError
    except TypeError as e:
        raise core.AppError("card_bad_file:{}".format(name))
    return path_front, path_back